﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using mshtml;
using System.Security.Permissions;
using System.Runtime.InteropServices;

using TCOE.ToolKits.Geolocation;

namespace GisGen
{
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [ComVisibleAttribute(true)]
    public partial class frmPointGenerate : Form
    {
        private IHTMLDocument2 domDoc = null;
        private IHTMLWindow2 win = null;

        public frmPointGenerate()
        {
            InitializeComponent();
        }

        private void frmPointGenerate_Load(object sender, EventArgs e)
        {
            Init();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            cbPointFormat.SelectedIndex = 0;
            cbOutFormat.SelectedIndex = 0;
            cbMap.SelectedIndex = 0;

        }

        // 清理地图
        private void ClearMap()
        {
            win.execScript("clearMap()", "javascript");
        }

        // 显示折线
        private void ShowLine(string points, string color)
        {
            win.execScript("showLine(\"" + points + "\",\"" + color + "\")", "javascript");
        }

        // 轨迹回放
        private void Replay(string points, string color)
        {
            win.execScript("replay(\"" + points + "\",\"" + color + "\")", "javascript");
        }

        // 显示坐标点
        private void ShowPoint(double lat, double lng)
        {
            win.execScript("showPoint(" + lat + "," + lng + ")", "javascript");
        }

        // 开始取点
        private void StartGetPoint()
        {
            win.execScript("startGetPoint()", "javascript");
        }

        // 结束取点
        private void EndGetPoint()
        {
            win.execScript("endGetPoint()", "javascript");
        }

        // 显示所取点
        public void ShowGetPoint(double lat,double lng)
        {
            txtGenerate.Text += lat + "," + lng + ";\r\n";
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {
            string source = txtSource.Text.Trim();
            double min = (double)nudMin.Value;
            double max = (double)nudMax.Value;
            double min0 = (double)nudMin0.Value;
            double max0 = (double)nudMax0.Value;

            if (source.Length == 0)
            {
                MessageBox.Show("源轨迹不能为空");
            }

            bool isLatLng = cbPointFormat.SelectedIndex == 0 ? true : false;
            IList<GpsPoint> lstPoint = ConvertToGpsPoint(source, isLatLng);

            // 计算补点
            string strGenPoints = "";
            GpsPoint prePoint = null;
            GpsPoint prePoint0 = null;
            bool fistGen = true;
            Random rd = new Random();
            foreach (GpsPoint p in lstPoint)
            {
                if (prePoint == null)
                {
                    prePoint = p;
                    continue;
                }

                // 生成坐标点
                IList<GpsPoint> lstGenPoint = GeneratePoint(prePoint, p, min, max);
                if (!fistGen)
                {
                    lstGenPoint.RemoveAt(0);
                }

                foreach (GpsPoint p0 in lstGenPoint)
                {
                    // 对坐标进行偏移
                    if (min0 != 0 || max0 != 0)
                    {
                        double offset = (rd.Next((int)min0, (int)max0) + rd.NextDouble()) / 100000;
                        p0.Longitude = p0.Longitude + offset;
                    }

                    double distance = 0.00;
                    if (prePoint0 != null)
                    {
                        distance = CoordCompute.GetDistance(prePoint0.Longitude, prePoint0.Latitude, p0.Longitude, p0.Latitude);
                    }

                    switch (cbOutFormat.SelectedIndex)
                    {
                        case 0:
                            strGenPoints += cbPointFormat.SelectedIndex == 0 ? p0.Latitude.ToString("F6") + "," + p0.Longitude.ToString("F6") + ";" : p0.Longitude.ToString("F6") + "," + p0.Latitude.ToString("F6") + ";";
                            break;
                        case 1:
                            string temp = cbPointFormat.SelectedIndex == 0 ? p0.LatitudeDegrees + "," + p0.LongitudeDegrees : p0.LongitudeDegrees + "," + p0.LatitudeDegrees;
                            strGenPoints += temp.Replace("°", ":").Replace("′", ":").Replace("″", "") + ";";
                            break;
                        case 2:
                            strGenPoints += cbPointFormat.SelectedIndex == 0 ? p0.LatitudeDegrees + "," + p0.LongitudeDegrees + ";" : p0.LongitudeDegrees + "," + p0.LatitudeDegrees + ";";
                            break;
                    }
                    if (cbDistanceShow.Checked)
                    {
                        strGenPoints += " " + distance + "\r\n";
                    }

                    strGenPoints += "\r\n";
                    prePoint0 = p0;
                }

                prePoint = p;
                fistGen = false;
            }
            txtGenerate.Text = strGenPoints;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtSource.Text = "";
            txtGenerate.Text = "";
            ClearMap();
        }

        private void btnMapShow1_Click(object sender, EventArgs e)
        {
            bool isLatLng = cbPointFormat.SelectedIndex == 0 ? true : false;
            IList<GpsPoint> lstGpsPoint = ConvertToGpsPoint(txtSource.Text.Trim(), isLatLng);

            string strPoints = "";
            foreach (GpsPoint p in lstGpsPoint)
            {
                strPoints += p.Latitude + "," + p.Longitude + ";";
            }

            ShowLine(strPoints, "#FF0000");
        }

        private void btnMapShow2_Click(object sender, EventArgs e)
        {

            bool isLatLng = cbPointFormat.SelectedIndex == 0 ? true : false;
            IList<GpsPoint> lstGpsPoint = ConvertToGpsPoint(txtGenerate.Text.Trim(), isLatLng);

            string strPoints = "";
            foreach (GpsPoint p in lstGpsPoint)
            {
                strPoints += p.Latitude + "," + p.Longitude + ";";
            }

            ShowLine(strPoints, "#0000FF");
        }

        private void btnLocation_Click(object sender, EventArgs e)
        {
            string strPoint = txtPoint.Text.Trim();
            if (strPoint.Length == 0)
            {
                MessageBox.Show("请输入坐标点");
                return;
            }

            bool isLatLng = cbPointFormat.SelectedIndex == 0 ? true : false;
            string[] point = strPoint.Split(',');
            GpsPoint p = new GpsPoint();
            if (isLatLng)
            {
                p.LatitudeText = point[0];
                p.LongitudeText = point[1];
            }
            else
            {
                p.LatitudeText = point[1];
                p.LongitudeText = point[0];
            }

            ShowPoint(p.Latitude, p.Longitude);
        }

        private void btnGetPoint_Click(object sender, EventArgs e)
        {
            if (btnGetPoint.Text == "开始取点")
            {
                StartGetPoint();
                btnGetPoint.Text = "结束取点";
            }
            else
            {
                EndGetPoint();
                btnGetPoint.Text = "开始取点";
            }
        }

        /// <summary>
        /// 生成坐标列表
        /// </summary>
        /// <param name="start">起始坐标</param>
        /// <param name="end">结束坐标</param>
        /// <param name="min">最小点距</param>
        /// <param name="max">最大点距</param>
        /// <returns>生成后坐标列表</returns>
        private IList<GpsPoint> GeneratePoint(GpsPoint start, GpsPoint end, double min, double max)
        {
            IList<GpsPoint> lstPoint = new List<GpsPoint>();
            lstPoint.Add(start);

            double distance = CoordCompute.GetDistance(start.Longitude, start.Latitude, end.Longitude, end.Latitude);
            double k_x = (end.Longitude - start.Longitude) / distance;  //x比斜边
            double k_y = (end.Latitude - start.Latitude) / distance;    //y比斜边


            Random ran = new Random();
            double interval = ran.Next((int)min, (int)max) + ran.NextDouble();//距离间隔

            int i = 0; //计数器
            double d = interval;
            while (d < distance)
            {
                i++;
                double x = d * k_x + start.Longitude;
                double y = d * k_y + start.Latitude;

                GpsPoint point = new GpsPoint();
                point.Longitude = x;
                point.Latitude = y;
                lstPoint.Add(point);

                interval = ran.Next((int)min, (int)max) + ran.NextDouble();
                d += interval;
            }

            lstPoint.Add(end);

            return lstPoint;
        }

        /// <summary>
        /// 坐标字符串转换为坐标列表
        /// </summary>
        /// <param name="strPoints">坐标字符串</param>
        /// <param name="isLatLng">坐标是（纬度，经度）格式（true:纬度，经度，false:经度，纬度）</param>
        /// <returns></returns>
        private IList<GpsPoint> ConvertToGpsPoint(string strPoints, bool isLatLng)
        {
            strPoints = strPoints.Replace("\r\n", "");
            string[] points = strPoints.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

            IList<GpsPoint> lstPoint = new List<GpsPoint>();
            foreach (string strPoint in points)
            {
                string[] latLng = strPoint.Split(',');
                GpsPoint point = new GpsPoint();
                if (isLatLng)
                {
                    //纬度，经度
                    point.LatitudeText = latLng[0];
                    point.LongitudeText = latLng[1];
                }
                else
                {
                    //经度，纬度
                    point.LatitudeText = latLng[1];
                    point.LongitudeText = latLng[0];
                }

                lstPoint.Add(point);
            }
            return lstPoint;
        }

        private void btnCaptionGenerate_Click(object sender, EventArgs e)
        {
            frmCaptionGenerate frmCaptionGenerate = new frmCaptionGenerate();
            frmCaptionGenerate.Show();
        }

        private void cbMap_SelectedIndexChanged(object sender, EventArgs e)
        {

            Uri url = null;
            if (cbMap.SelectedItem.ToString() == "百度地图")
            {
                string address = "File:\\" + Application.StartupPath + "\\map_bd.html";
                url = new Uri(address);
            }
            else
            {
                string address = "File:\\" + Application.StartupPath + "\\map_gd.html";
                url = new Uri(address);    
            }
            wbMap.Url = url;
            wbMap.ObjectForScripting = this;
            domDoc = (IHTMLDocument2)wbMap.Document.DomDocument;
            win = (IHTMLWindow2)domDoc.parentWindow;
        }

        private void btnReplay_Click(object sender, EventArgs e)
        {
            bool isLatLng = cbPointFormat.SelectedIndex == 0 ? true : false;
            IList<GpsPoint> lstGpsPoint = ConvertToGpsPoint(txtGenerate.Text.Trim(), isLatLng);

            string strPoints = "";
            foreach (GpsPoint p in lstGpsPoint)
            {
                strPoints += p.Latitude + "," + p.Longitude + ";";
            }

            Replay(strPoints, "#0000FF");
        }
    }
}
